package com.example.customeview.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class MySlideRecyclerView extends RecyclerView {
    /**
     * 判断是否是横向滑动
     */
    private boolean isMoving;

    /**
     * 速度追踪器
     */
    private VelocityTracker mTracter;
    /**
     * 最小滑动速度
     */
    private static final int MIUM_VEC = 500;

    /**
     * 左滑的工具
     */
    private Scroller mSroller;
    /**
     * item的两种状态
     * mMoveView指手指按压在屏幕上，Item的状态
     * mLastView指手指离开屏幕后，Item的状态
     */
    private ViewGroup mLastView;
    private ViewGroup mMoveView;
    /**
     * 最小滑动距离
     */
    private int mTouchslop;
    /**
     * 菜单栏的宽度
     */
    private int mItemWidth;

    private int mFirstX;
    private int mFirstY;
    private int mLastX;


    public MySlideRecyclerView(@NonNull Context context) {
        this(context, null);
    }

    public MySlideRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MySlideRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    /**
     * 初始化操作
     *
     * @param context
     */
    private void init(Context context) {
        mSroller = new Scroller(context);
        mTouchslop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        int x = (int) e.getX();
        int y = (int) e.getY();
        obtainVeloctity(e);
        switch (e.getAction()){
            case MotionEvent.ACTION_DOWN:
                if (!mSroller.isFinished()) {
                    mSroller.abortAnimation();
                }
                mFirstX = x;
                mFirstY = y;
                mLastX = x;
                mMoveView = (ViewGroup) findChildViewUnder(x, y);
                if(mLastView!=null && mLastView.getScrollX()!=0 && mLastView!=mMoveView){
                    closeMenu();
                }
                if(mMoveView!=null && mMoveView.getChildCount()>=2){
                    mItemWidth = mMoveView.getChildAt(1).getWidth();
                }
                else{
                    mItemWidth = -1;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                //判断是否是横向滑动
                int moveX = Math.abs(x - mFirstX);
                int moveY = Math.abs(y - mFirstY);
                mTracter.computeCurrentVelocity(1000);
                int velocityX = Math.abs((int) mTracter.getXVelocity());
                int velocityY  = Math.abs((int) mTracter.getYVelocity());
                boolean isHoriableMove = ((moveX > moveY && moveX > mTouchslop)
                        || (velocityX > velocityY && velocityX > MIUM_VEC))
                        && mItemWidth != -1
                        && getScrollState() == 0;
                if(isHoriableMove){
                    isMoving=true;
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                releaseVeloctity();
                closeMenuNow();
                break;
            default:
                break;

        }
        return super.onInterceptTouchEvent(e);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        int x = (int) e.getX();
        int y = (int) e.getY();
        obtainVeloctity(e);
        switch (e.getAction())
        {
            case MotionEvent.ACTION_MOVE:
                if(isMoving){
                    //判断左滑还是右滑动
                    int dx = mLastX - x;
                    if(dx+ mMoveView.getScrollX()<= mItemWidth && dx+mMoveView.getScrollX()>=0){
                        //跟手滑动
                        mMoveView.scrollBy(dx,0);
                    }
                    mLastX=x;
                    return true;
                }
                else{
                    //二次判断
                    int moveX = Math.abs(x - mFirstX);
                    int moveY = Math.abs(y - mFirstY);
                    mTracter.computeCurrentVelocity(1000);
                    int velocityX = Math.abs((int) mTracter.getXVelocity());
                    int velocityY  = Math.abs((int) mTracter.getYVelocity());
                    boolean isHoriableMove = ((moveX > moveY && moveX > mTouchslop)
                            || (velocityX > velocityY && velocityX > MIUM_VEC))
                            && mItemWidth != -1
                            && getScrollState() == 0;
                    if(isHoriableMove){
                        int dx = mLastX - x;
                        if(dx+mMoveView.getScrollX()<=mItemWidth && dx+mMoveView.getScrollX()>=0){
                            //跟手滑动
                            mMoveView.scrollBy(dx,0);
                        }
                        isMoving=true;
                        mLastX = x;
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if(isMoving){
                    if(!mSroller.isFinished())
                    {
                        mSroller.abortAnimation();
                        mLastView.scrollTo(mSroller.getFinalX(),0);
                    }
                    isMoving = false;
                    mLastView = mMoveView;
                    int scrollX = mLastView.getScrollX();
                    mTracter.computeCurrentVelocity(1000);
                    int xVelocity = (int) mTracter.getXVelocity();
                    if(xVelocity<-MIUM_VEC || scrollX>mItemWidth/2)
                    {
                        mSroller.startScroll(scrollX,0,mItemWidth-scrollX,0,
                                Math.abs(mItemWidth-scrollX));
                    }
                    else{
                        mSroller.startScroll(scrollX,0,-scrollX,0,Math.abs(scrollX));
                    }
                    invalidate();
                }
                else if(mLastView!=null && mLastView.getScrollX()!=0){
                    closeMenuNow();
                }
                releaseVeloctity();
                break;
            default:
                break;
        }
        return super.onTouchEvent(e);
    }

    /**
     * 使用过scroller必须覆盖的方法
     */
    @Override
    public void computeScroll() {
        //computeScrollOffset() 计算当前滑动是否已完成
        if (mSroller.computeScrollOffset()) {
            //未完成
            if (isInWindow(mLastView)) {
                mLastView.scrollTo(mSroller.getCurrX(), 0);
                invalidate();
            } else {
                //当前界面
                mSroller.abortAnimation();
                mLastView.scrollTo(mSroller.getFinalX(), 0);
            }
        }

    }

    /**
     * 判断当前的item是否在界面上
     *
     * @param mLastView
     * @return
     */
    private boolean isInWindow(ViewGroup mLastView) {
        LayoutManager layoutManager = getLayoutManager();
        boolean isInwindow = false;
        if (layoutManager instanceof LinearLayoutManager) {
            int firstPos = ((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition();
            int lastPos = ((LinearLayoutManager) layoutManager).findLastCompletelyVisibleItemPosition();
            int position = layoutManager.getPosition(mLastView);
            isInwindow = position >= firstPos && position <= lastPos;
        }
        return isInwindow;
    }

    /**
     * 获取速度检测器
     *
     * @param event
     */
    private void obtainVeloctity(MotionEvent event) {
        if (mTracter == null) {
            mTracter = VelocityTracker.obtain();
        }
        mTracter.addMovement(event);
    }

    /**
     * 释放速度检测器
     */
    private void releaseVeloctity() {
        if (mTracter != null) {
            mTracter.clear();
            mTracter.recycle();
            mTracter = null;
        }
    }

    /**
     * 关闭菜单栏
     */
    private void closeMenu() {
        mSroller.startScroll(mLastView.getScrollX(), 0, -mLastView.getScrollX(), 0, Math.abs(mLastView.getScrollX()));
        invalidate();
    }

    /**
     * 立即关闭菜单栏
     */
    private void closeMenuNow() {
        if (mLastView != null && mLastView.getScrollX() != 0) {
            mLastView.scrollTo(0, 0);
        }
    }

}
